package com.zyj;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Version;

import java.io.IOException;
import java.util.List;

public class Lucene2FindDemo {


    public static void main(String[] args) throws Exception {
         findAll(LuceneUtils.getDirectory());
         // 精确查询
         findByTerm(LuceneUtils.getDirectory(), new Term("title", "中"));

         //范围查询
         findByRange(LuceneUtils.getDirectory(),LuceneUtils.stringToTime("2018-08-20 00:00:00"),LuceneUtils.stringToTime("2018-08-22 00:00:00" ));

         //前缀查询
        findByPrefix(LuceneUtils.getDirectory(), new Term("email", "z"));

        //通配查询
        findByWildcard(LuceneUtils.getDirectory(), new Term("email", "*san"));


        //解析器查找
        findByPhase(LuceneUtils.getDirectory());


    }
    private static void findByPhase(Directory directory) throws IOException, InvalidTokenOffsetsException, ParseException {
        System.out.println("\n解析器查询");
        QueryParser parse = new QueryParser(Version.LUCENE_47, "content", LuceneUtils.getAnalyzer());
        //parse.setDefaultOperator(QueryParser.Operator.AND);//将空格默认 定义为AND  初始是 OR

        Query query = parse.parse("中");

        //其中空格默认就是OR
          query = parse.parse("环 道");

         //改变搜索域，搜索域 为 email
        query = parse.parse("email:zhangsan");

//        //使用通配符 ， 设定查询类容为 以 z 开头的数据
        query = parse.parse("email:z*"); //其中* 不可以放在字符串的首位

//        //将字符串放在首位，默认情况下回报错
   //      parse.setAllowLeadingWildcard(true);//设定第一个* 可以匹配
        query = parse.parse("email:@cc.com");


        excQuery(directory, query);
    }


    private static void findByPrefix(Directory directory, Term trem) throws IOException, InvalidTokenOffsetsException {
        System.out.println("\n前缀查找:" + trem);
        Query query  =  new PrefixQuery(trem);
        excQuery(directory, query);
    }

    private static void findByWildcard(Directory directory, Term trem) throws IOException, InvalidTokenOffsetsException {
        System.out.println("\n通配查找:" + trem);
        Query query  =  new WildcardQuery(trem);
        excQuery(directory, query);
    }





    private static void findByRange(Directory directory,Long start, Long end) throws IOException, InvalidTokenOffsetsException {
        //minInclusive 包含最小 maxInclusive包含最大
        System.out.println("\n范围查找date:" + start +"-" + end);
        Query query = NumericRangeQuery.newLongRange("date",start, end, true,true);
        excQuery(directory, query);
    }


    private static void findByTerm(Directory directory, Term trem) throws IOException, InvalidTokenOffsetsException {
        System.out.println("\n精确查找:" + trem);
        Query query  =  new TermQuery(trem);
        excQuery(directory, query);
    }



    public static void excQuery(Directory directory, Query query) throws IOException, InvalidTokenOffsetsException {
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);//初始化查询组件
        TopDocs topDocs = searcher.search(query,3);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        System.out.println("总记录数:" + topDocs.totalHits +"当前命中数：" + scoreDocs.length);

        for (ScoreDoc scoreDoc : scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            stoutDoc(doc, scoreDoc.doc);
        }

        //设置高亮
      /*  SimpleHTMLFormatter simpleHtmlFormatter = new SimpleHTMLFormatter("【","】");
        QueryScorer scorer = new QueryScorer(query);
        Highlighter highlighter = new Highlighter(simpleHtmlFormatter,scorer);
        System.out.println("==========设置搜索高亮============");
        for (ScoreDoc scoreDoc : scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            String str = highlighter.getBestFragment(LuceneUtils.getAnalyzer(), "title", doc.get("title"));
            System.out.println(str);
        }*/
    }

    public static void findAll(Directory  directory) throws IOException {
        IndexReader reader = DirectoryReader.open(directory);
        int maxDoc = reader.maxDoc();//所有文档数
        System.out.println("\n查询所有文档：当前有效数：" + reader.numDocs() + "当前最大数:" + maxDoc);
        IndexSearcher searcher = new IndexSearcher(reader);//初始化查询组件
        for (int i = 0 ; i <maxDoc ; i ++) {
            Document doc =  searcher.doc(i);
            stoutDoc(doc, i);
        }
    }


    private static void stoutDoc(Document doc, int docId) {
        List<IndexableField> listField = doc.getFields();
        StringBuffer stringBuffer = new StringBuffer("docId:").append(docId).append("\t");
        for ( int j = 0;j < listField.size(); j++){
            IndexableField index = listField.get(j);
            stringBuffer.append(index.name()).append(":").append(index.stringValue()).append("\t");
        }
        System.out.println(stringBuffer.toString());
    }

}
